package com.googlecode.horncomb.organ.srvc.support;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.util.Assert;

import com.googlecode.horncomb.bean.filter.SimpleMapConditionSet;
import com.googlecode.horncomb.bean.order.DefaultOrder;
import com.googlecode.horncomb.organ.Group;
import com.googlecode.horncomb.organ.Person;
import com.googlecode.horncomb.organ.srvc.GroupService;
import com.googlecode.horncomb.organ.support.OrganObject;
import com.googlecode.horncomb.orm.ibatis.DefaultCommonSqlMapEntityDao;

/**
 * @author Daniel
 */
public class DefaultGroupService extends DefaultCommonSqlMapEntityDao implements
		GroupService {
	private static final long serialVersionUID = 2897867385579906930L;
	private String updateStateStatementName = "updateState";

	/**
	 * {@inheritDoc}
	 */
	public int countMembers(String groupId, String[] memberNatures,
			String[] membershipNatures) {
		Map<String, Object> membership = new HashMap<String, Object>();
		membership.put("natures", membershipNatures);
		membership.put("memberNatures", memberNatures);
		membership.put("groupId", groupId);
		return this.queryCount(new SimpleMapConditionSet().addConstraint(
				"membership", membership), "countMembers");
	}

	/**
	 * {@inheritDoc}
	 */
	public int countMembers(Collection<String> groupIds,
			String[] memberNatures, String[] membershipNatures) {
		Map<String, Object> membership = new HashMap<String, Object>();
		membership.put("natures", membershipNatures);
		membership.put("memberNatures", memberNatures);
		membership.put("groupIds", groupIds);
		return this.queryCount(new SimpleMapConditionSet().addConstraint(
				"membership", membership));
	}

	/**
	 * {@inheritDoc}
	 */
	public int countSources(String targetId, String[] sourceNatures,
			String[] relationNatures) {
		Map<String, Object> groupRelation = new HashMap<String, Object>();
		groupRelation.put("targetId", targetId);
		groupRelation.put("sourceNatures", sourceNatures);
		groupRelation.put("natures", relationNatures);
		return this.queryCount(new SimpleMapConditionSet().addConstraint(
				"groupRelation", groupRelation));
	}

	/**
	 * {@inheritDoc}
	 */
	public int countSources(Collection<String> targetIds, String[] sourceNatures,
			String[] relationNatures) {
		Map<String, Object> groupRelation = new HashMap<String, Object>();
		groupRelation.put("targetIds", targetIds);
		groupRelation.put("sourceNatures", sourceNatures);
		groupRelation.put("natures", relationNatures);
		return this.queryCount(new SimpleMapConditionSet().addConstraint(
				"groupRelation", groupRelation));
	}

	/**
	 * {@inheritDoc}
	 */
	public int countTargets(String sourceId, String[] targetNatures,
			String[] relationNatures) {
		Map<String, Object> groupRelation = new HashMap<String, Object>();
		groupRelation.put("sourceId", sourceId);
		groupRelation.put("targetNatures", targetNatures);
		groupRelation.put("natures", relationNatures);
		return this.queryCount(new SimpleMapConditionSet().addConstraint(
				"groupRelation", groupRelation));
	}

	/**
	 * {@inheritDoc}
	 */
	public int countTargets(Collection<String> sourceIds, String[] targetNatures,
			String[] relationNatures) {
		Map<String, Object> groupRelation = new HashMap<String, Object>();
		groupRelation.put("sourceIds", sourceIds);
		groupRelation.put("targetNatures", targetNatures);
		groupRelation.put("natures", relationNatures);
		return this.queryCount(new SimpleMapConditionSet().addConstraint(
				"groupRelation", groupRelation));
	}

	/**
	 * {@inheritDoc}
	 */
	public void create(Group group) {
		Assert.notNull(group);
		group.setCreated(new Date());
		group.setState(OrganObject.STATE_ACTIVE);
		group.setLastUpdated(group.getCreated());
		this.insert(group);
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	public List<? extends Person> findMembers(String groupId,
			String[] memberNatures, String[] membershipNatures) {
		Map<String, Object> membership = new HashMap<String, Object>();
		membership.put("natures", membershipNatures);
		membership.put("memberNatures", memberNatures);
		membership.put("groupId", groupId);
		return this.query(new SimpleMapConditionSet().addConstraint(
				"membership", membership), new DefaultOrder().addSortToken(
				"GRO_GRP_ORDER_").addSortToken("MEM_PSN_ORDER_"));
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	public List<? extends Person> findMembers(Collection<String> groupIds,
			String[] memberNatures, String[] membershipNatures) {
		Map<String, Object> membership = new HashMap<String, Object>();
		membership.put("natures", membershipNatures);
		membership.put("memberNatures", memberNatures);
		membership.put("groupIds", groupIds);
		return this.query(new SimpleMapConditionSet().addConstraint(
				"membership", membership), new DefaultOrder().addSortToken(
				"GRO_GRP_ORDER_").addSortToken("MEM_PSN_ORDER_"));
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	public List<? extends Group> findSources(String targetId,
			String[] sourceNatures, String[] relationNatures) {
		Map<String, Object> groupRelation = new HashMap<String, Object>();
		groupRelation.put("targetId", targetId);
		groupRelation.put("sourceNatures", sourceNatures);
		groupRelation.put("natures", relationNatures);
		return this.query(new SimpleMapConditionSet().addConstraint(
				"groupRelation", groupRelation), new DefaultOrder()
				.addSortToken("GRE_SRC_ORDER_"));
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	public List<? extends Group> findSources(Collection<String> targetIds,
			String[] sourceNatures, String[] relationNatures) {
		Map<String, Object> groupRelation = new HashMap<String, Object>();
		groupRelation.put("targetIds", targetIds);
		groupRelation.put("sourceNatures", sourceNatures);
		groupRelation.put("natures", relationNatures);
		return this.query(new SimpleMapConditionSet().addConstraint(
				"groupRelation", groupRelation), new DefaultOrder()
				.addSortToken("GRE_SRC_ORDER_"));
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	public List<? extends Group> findTargets(String sourceId,
			String[] targetNatures, String[] relationNatures) {
		Map<String, Object> groupRelation = new HashMap<String, Object>();
		groupRelation.put("sourceId", sourceId);
		groupRelation.put("targetNatures", targetNatures);
		groupRelation.put("natures", relationNatures);
		return this.query(new SimpleMapConditionSet().addConstraint(
				"groupRelation", groupRelation), new DefaultOrder()
				.addSortToken("GRE_TRG_ORDER_"));
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	public List<? extends Group> findTargets(Collection<String> sourceIds,
			String[] targetNatures, String[] relationNatures) {
		Map<String, Object> groupRelation = new HashMap<String, Object>();
		groupRelation.put("sourceIds", sourceIds);
		groupRelation.put("targetNatures", targetNatures);
		groupRelation.put("natures", relationNatures);
		return this.query(new SimpleMapConditionSet().addConstraint(
				"groupRelation", groupRelation), new DefaultOrder()
				.addSortToken("GRE_TRG_ORDER_"));
	}

	/**
	 * {@inheritDoc}
	 */
	public Group getById(String groupId) {
		return this.getById(groupId);
	}

	/**
	 * {@inheritDoc}
	 */
	public Person getGroupMaster(String groupId, String personNature,
			String membershipNature) {
		Map<String, Object> membership = new HashMap<String, Object>();
		membership.put("nature", membershipNature);
		membership.put("personNature", personNature);
		membership.put("groupId", groupId);
		return (Person) this.doGet(new SimpleMapConditionSet().addConstraint(
				"membership", membership));
	}

	/**
	 * @param personId
	 * @param stateDelelted
	 */
	private void updateState(String personId, String state) {
		Map<String, Object> entity = new HashMap<String, Object>();
		entity.put("state", state);
		this.doUpdate(
				new SimpleMapConditionSet().addConstraint("id", personId),
				entity, this.updateStateStatementName);
	}

	/**
	 * {@inheritDoc}
	 */
	public void removeById(String groupId, boolean deleted) {
		this.updateState(groupId, deleted ? OrganObject.STATE_DELELTED
				: OrganObject.STATE_ACTIVE);
	}

	/**
	 * {@inheritDoc}
	 */
	public void update(Group group) {
		Assert.notNull(group);
		group.setLastUpdated(new Date());
		this.update(group);
	}

	/**
	 * @param updateStateStatementName
	 *            the updateStateStatementName to set
	 */
	public void setUpdateStateStatementName(String updateStateStatementName) {
		this.updateStateStatementName = updateStateStatementName;
	}
}
